package com.caocaog.market.finance.calculation;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.caocaog.market.constant.MarketConstant;
import com.caocaog.market.finance.entity.MkBillBase;
import com.caocaog.market.finance.entity.MkBillLine;
import com.caocaog.market.finance.entity.MkBillLineHistory;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.util.DateUtils;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.*;

/**
 * @author liguang
 * @version 1.0.0
 * @Project jeecg-boot
 * @Package com.caocaog.market.finance.calculation
 * @ClassName Calculate.java
 * @createTime 2021年12月04日 11:50:00
 * @Description 计算类
 */
public class Calculate {
    /**
     *  结算天数（settlement_time字段，单位是天）、总部的抽成比例（sys_rake_rate字段/100）是从mk_site_basic中取的；
     *  分站抽成  是从mk_shop_basic中取的 commission_rate  字段
     *      1、查询出所有待结算的账单根据系统给每个分站设置的结算天数判断该账单是否可以进行结算
     *          1.1 查询出所有待结算的账单
     *          1.2 看这些待结算的账单属于哪个分站  查询出该分站的待结算时间以及抽成比例
     *          1.3 进入第2步进行计算
     *
     *      2、根据每个订单所属的商家、分站（抽成比例）  以及   系统(抽成比例)  来进行分成计算
     *
     *      3、每个单子的抽成比例、金额算好之后 存入mk_bill_line 以及  mk_bill_history表中
     */

    /**
     * 如果没有填写系统没有设置分站的抽成比例，就按1%算
     */
    private final static String sysRate = "1";
    /**
     * 如果分站没有填写门店的抽成比例，就按0%算
     */
    private final static String siteRate = "0";
    /**
     *  计算百分比用
     */
    private final static int percent = 100;
    /**
     *  计算 0
     */
    private final static int zero = 0;

    /**
     * 系统预定的待结算天数
     */
    private final static String days = "3";

    /**
     * 保留几位小数
     */
    private final static int n=2;
    /**  默认用户名  */
    private final static String systemUsername="admin";
    /** 默认系统的支付宝账号 */
    private final static String systemAlipay="system";
    /** 默认系统的支付宝姓名 */
    private final static String systemAliname="曹操来了系统";
    private static List<MkBillBase> settlementBaseList = null;

    public static  List<MkBillLineHistory>  compute(List<MkBillBase> billBaseList){
        List<MkBillLineHistory> billLineList = new ArrayList<MkBillLineHistory>();
        Date currentDate = DateUtils.getDate();
        /**
         * 符合结算条件的，全部加到list里面
         */
        settlementBaseList = new ArrayList<MkBillBase>();
        Map<String,String> balanceIdMap = new HashMap<String,String>();
        for(MkBillBase bill : billBaseList){
            String siteAlipay = bill.getSiteAlipay(),siteAliname = bill.getSiteAliname(),
                    merchantAlipay = bill.getMerchantAlipay(),merchantAliname = bill.getMerchantAliname(),
                    shopAlipay = bill.getShopAlipay(),shopAliname = bill.getShopAliname(),shopId = bill.getShopId(),merchantId = bill.getMerchantId();
            if(StringUtils.isBlank(siteAliname) || StringUtils.isBlank(siteAlipay)){
                /**
                 * 分站支付宝账号、分站支付宝姓名  有任意一个为空，不结算
                 */
                continue;
            }
            if(StringUtils.isBlank(shopAliname) || StringUtils.isBlank(shopAlipay)){
                /**
                 * 如果门店支付宝账号、门店支付宝姓名   有任意一方为空，则取商家的支付宝姓名和支付宝账号
                 */
                shopAliname = merchantAliname;
                shopAlipay = merchantAlipay;
                //shopId = merchantId;
            }
            if(StringUtils.isBlank(shopAliname) || StringUtils.isBlank(shopAlipay)){
                /**
                 * 取过商家的支付宝账号和支付宝姓名之后
                 * 如果门店支付宝姓名或门店支付宝账号  其中一方再为空，不结算
                 */
                continue;
            }
            /**
             * 先按时间计算，是否达到结算的标准
             * 付款时间  格式：yyyy-MM-dd HH:mm:ss
             */
            Date payTime = bill.getPayTime();
            /**
             * 总部给分站设置的待结算天数
             * 如果没有设置，则按3天算
             */
            String settleDays = bill.getSittleTime();
            BigDecimal settleDaysDecimal = null;
            try{
                settleDaysDecimal = new BigDecimal(settleDays);
            }catch (Exception e){
                settleDaysDecimal = new BigDecimal(days);
            }
            /**
             * 根据设置的 待结算天数
             *      计算 加上 待结算天数 之后 的日期
             */
            Date afterDaysDate = DateUtils.dateAddDays(payTime,Integer.parseInt(settleDaysDecimal.toString()));
            // 系统的毫秒数
            long sysMillis = DateUtils.getMillis();
            // afterDaysDate的毫秒数
            long afterDaysDateMillis = DateUtils.getMillis(afterDaysDate);
            /**
             * 如果加三天之后之后 大于 当前日期的毫秒数就说明 没有达到 结算标准
             * 例：
             *      1、支付时间是：2021-12-01 09:15:05
             *              加三天
             *          之后是 2021-12-04 09：15：05
             *          此时，这个日期小于当前日期（2021-12-06 09：15：05）是可以结算的
             *      2、支付时间是：2021-12-04 09：15：12
             *              加三天
             *         之后是  2021-12-07 09：15：05
             *         此时，这个日期大于当前日期（2021-12-06 09：15：05）是不可以结算的
             *
              */
            if(afterDaysDateMillis > sysMillis){
                // 没有达到结算标准，直接continue
                continue;
            }
            // 符合结算条件的全部加入到settlementBaseList里面
            settlementBaseList.add(bill);
            /**
             * 如果加三天之后，小于或等于当前日期的毫秒数就说明  已经达到  结算标准
             */
            // 订单金额
            String billAmount = bill.getPayAmount();
            // 如果订单金额是空值
            billAmount = StringUtils.isBlank(billAmount)  ? "0" : billAmount;
            BigDecimal amountDecimal = null;
            /**
             * try.....catch...   主要是验证billAmount能不能转换成数字
             * 如果不能转换为数字，则按 0 算
             */
            try{
                amountDecimal =  new BigDecimal(billAmount);
            }catch (Exception e){
                amountDecimal = new BigDecimal(zero);
            }
            // 系统抽成比例
            String sysRakeRate = StringUtils.isBlank(bill.getSysRakeRate()) ? sysRate : bill.getSysRakeRate();
            BigDecimal sysRateDecimal = new BigDecimal(sysRakeRate);
            BigDecimal percentDecimal = new BigDecimal(percent);
            /**
             *  divide 除法，结果是小数，系统的抽成比例
             */
            BigDecimal sysRatePercentDecimal = sysRateDecimal.divide(percentDecimal);
            /**
             *
             * 分站抽成比例，是小数
             * */
            String siteRakeRate = StringUtils.isBlank(bill.getShopRate()) ? siteRate : bill.getShopRate();
            BigDecimal siteRateDecimal = null;
            /**
             * 先判断能不能转成BigDecimal
             *  如果不能转，就按 0 算
             */
            try{
                siteRateDecimal = new BigDecimal(siteRakeRate);
            }catch (Exception e ){
                siteRateDecimal = new BigDecimal(zero);
            }
            /**
             * 计算门店的收益比例
             *      = 1 - 系统提成比例 - 分站提成比例
             */
            BigDecimal shopRateDecimal = new BigDecimal(1).subtract(sysRatePercentDecimal).subtract(siteRateDecimal);
            /**
             * 系统、分站、门店   三方收益比例都算出来之后，根据总金额和比例算各方收益
             */
            /**  1、计算门店收益（除了系统和分站拿走的提成，剩下的钱）；保留两位小数，多于两位的小数直接舍去 */
            BigDecimal shopMoneyDecimal = amountDecimal.multiply(shopRateDecimal).setScale(n,BigDecimal.ROUND_DOWN);

            /**    2、计算分站收益（即：分站的提成）；保留两位小数，多于两位的小数直接舍去 */
            BigDecimal siteMoneyDecimal = amountDecimal.multiply(siteRateDecimal).setScale(n,BigDecimal.ROUND_DOWN);
            /**    3、计算系统的收益（即：系统的提成）；
             *        理论上：
             *              系统收益1 = 订单总金额  *  系统抽成比例
             *              系统收益2 = 订单总金额 - 分站提成 - 门店收益
             *        理论上而言，系统收益1 = 系统收益2
             *        但实际上，系统收益1 ！= 系统收益2；
             *          这是因为在计算过程中有小数的原因，
             *          而从第三位开始小数部分是直接被舍去的，
             *          即使按照四舍五入计算  系统收益1 也不一定完全等于系统收益2
             *       所以采用”系统收益2“的算法：先计算两方收益，用总金额减去这两方收益  剩下的都是第三方的，只有这样才能保证：
             *          系统收益 + 分站收益 + 门店收益  =  订单总金额
             * */
            BigDecimal sysMoneyDecimal = amountDecimal.subtract(siteMoneyDecimal).subtract(shopMoneyDecimal);
            /**
             *  一个账单需要存三个账单行；
             *  分别是：系统、分站、门店  三方的收益
             *  存账单行 以及  存账单行历史记录
             */
            MkBillLineHistory sysBillLineHistory = new MkBillLineHistory();
            // 主键id
            sysBillLineHistory.setId(IdWorker.getIdStr(sysBillLineHistory));
            // 对应的账单id
            sysBillLineHistory.setBillBaseId(bill.getId());
            // 收益比例
            sysBillLineHistory.setRakeRate(sysRatePercentDecimal.toString());
            // 订单号
            sysBillLineHistory.setOrderNo(bill.getOrderNo());
            // 收益金额
            sysBillLineHistory.setRakeAmount(sysMoneyDecimal.toString());
            // 类型
            sysBillLineHistory.setType(MarketConstant.FINANCE_BILL_LINE_TYPE_SYS);
            // 备注
            sysBillLineHistory.setMark(MarketConstant.FINANCE_BILL_LINE_MARK_NORMAL_SETTLE);
            sysBillLineHistory.setBillLineId(IdWorker.getIdStr(new MkBillLine()));
            sysBillLineHistory.setCreateTime(currentDate);
            sysBillLineHistory.setCreateBy(systemUsername);
            sysBillLineHistory.setRakeAliname(systemAliname);
            sysBillLineHistory.setRakeAlipay(systemAlipay);
            sysBillLineHistory.setRakeUserId("0");
            billLineList.add(sysBillLineHistory);

            MkBillLineHistory siteBillLineHistory = new MkBillLineHistory();
            // 主键id
            siteBillLineHistory.setId(IdWorker.getIdStr(siteBillLineHistory));
            // 对应的账单id
            siteBillLineHistory.setBillBaseId(bill.getId());
            // 收益比例
            siteBillLineHistory.setRakeRate(siteRateDecimal.toString());
            // 订单号
            siteBillLineHistory.setOrderNo(bill.getOrderNo());
            // 收益金额
            siteBillLineHistory.setRakeAmount(siteMoneyDecimal.toString());
            // 类型
            siteBillLineHistory.setType(MarketConstant.FINANCE_BILL_LINE_TYPE_SITE);
            // 备注
            siteBillLineHistory.setMark(MarketConstant.FINANCE_BILL_LINE_MARK_NORMAL_SETTLE);
            siteBillLineHistory.setBillLineId(IdWorker.getIdStr(new MkBillLine()));
            siteBillLineHistory.setCreateTime(currentDate);
            siteBillLineHistory.setCreateBy(systemUsername);
            siteBillLineHistory.setRakeAliname(siteAliname);
            siteBillLineHistory.setRakeAlipay(siteAlipay);
            siteBillLineHistory.setRakeUserId(bill.getSiteId());
            billLineList.add(siteBillLineHistory);

            MkBillLineHistory shopBillLineHistory = new MkBillLineHistory();
            // 主键id
            shopBillLineHistory.setId(IdWorker.getIdStr(shopBillLineHistory));
            // 对应的账单id
            shopBillLineHistory.setBillBaseId(bill.getId());
            // 收益比例
            shopBillLineHistory.setRakeRate(shopRateDecimal.toString());
            // 订单号
            shopBillLineHistory.setOrderNo(bill.getOrderNo());
            // 收益金额
            shopBillLineHistory.setRakeAmount(shopMoneyDecimal.toString());
            // 类型
            shopBillLineHistory.setType(MarketConstant.FINANCE_BILL_LINE_TYPE_SHOP);
            // 备注，存的是汉字
            shopBillLineHistory.setMark(MarketConstant.FINANCE_BILL_LINE_MARK_NORMAL_SETTLE);
            shopBillLineHistory.setBillLineId(IdWorker.getIdStr(new MkBillLine()));
            shopBillLineHistory.setCreateTime(currentDate);
            shopBillLineHistory.setCreateBy(systemUsername);
            shopBillLineHistory.setRakeAliname(shopAliname);
            shopBillLineHistory.setRakeAlipay(shopAlipay);
            shopBillLineHistory.setRakeUserId(shopId);
            billLineList.add(shopBillLineHistory);
        }
        /**
         * 存结算后的余额信息
         */

        return billLineList;
    }
    /**
     * 获取符合结算条件的所有账单信息
     */
    public static List<MkBillBase> getSettlementBaseList(){
        return settlementBaseList;
    }


    public static void main(String[] args) throws ParseException {
        String str=".355555555559";
        BigDecimal bigDecimal = new BigDecimal(str);
        System.out.println(bigDecimal);
       /* BigDecimal sysRateDecimal = new BigDecimal("1.10000000000000000000000000000005");
        BigDecimal percentDecimal = new BigDecimal(percent);
        BigDecimal sysRatePercent = sysRateDecimal.divide(percentDecimal);
        System.out.println(sysRatePercent);*/
      /*  SimpleDateFormat format = new   SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date dd  = format.parse("2020-12-29 12:15:02");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dd);
        calendar.add(Calendar.DAY_OF_MONTH, 3);
        String T3 = format.format(calendar.getTime());
        System.out.println("Ts---->   "+calendar.getTime());*/
    }


}
